<?php

namespace app\apiadmin\service\TCSS;

use app\apiadmin\controller\liveManager\LiveStatus;
use app\apiadmin\controller\user\User;
use app\apiadmin\service\statics\LiveUserStaticsService;
use Exception;
use function Symfony\Component\DependencyInjection\Loader\Configurator\param;
use Tencent\TLSSigAPIv2;
use think\facade\Db;
use think\facade\Log;
use \Predis\Client;

/**
 * 腾讯 css 直播业务封装类
 */
class TImService
{
    /**
     * im instance
     *
     * @varHedeqiang\TenIM\IM
     */
    private $im;
    private $sdkappid;
    private $_key;
    private $identifier;
    private $_isDebuger = false;

    private $errInfo = [
        "60002" => "HTTP 解析错误 ，请检查 HTTP 请求 URL 格式",
        "60003" => "HTTP 请求 JSON 解析错误，请检查 JSON 格式",
        "60004" => "请求 URL 或 JSON 包体中账号或签名错误",
        "60005" => "请求 URL 或 JSON 包体中账号或签名错误",
        "60006" => "SDKAppID 失效，请核对 SDKAppID 有效性",
        "60007" => "REST 接口调用频率超过限制，请降低请求频率",
        "60008" => "服务请求超时或 HTTP 请求格式错误，请检查并重试",
        "60009" => "请求资源错误，请检查请求 URL",
        "60010" => "请求需要 App 管理员权限",
        "60011" => "SDKAppID 请求频率超限，请降低请求频率",
        "60012" => "REST 接口需要带 SDKAppID，请检查请求 URL 中的 SDKAppID",
        "60013" => "HTTP 响应包 JSON 解析错误",
        "60014" => "置换账号超时",
        "60015" => "请求包体账号类型错误，请确认账号为字符串格式",
        "60016" => "SDKAppID 被禁用。",
        "60017" => "请求被禁用。",
        "60018" => "请求过于频繁，请稍后重试。",
        "60019" => "请求过于频繁，请稍后重试。",
        "60020" => "您的专业版套餐包已到期并停用，请登录 即时通信 IM 购买页面 重新购买套餐包。购买后，将在5分钟后生效。",
        "60021" => "RestAPI 调用来源 IP 非法。",

    ];

    const ENDPOINT_TEMPLATES = [
        'zh' => 'https://console.tim.qq.com/%s/%s/%s?%s',
        'sgp' => 'https://adminapisgp.im.qcloud.com/%s/%s/%s?%s',
        'kr' => 'https://adminapikr.im.qcloud.com/%s/%s/%s?%s',
        'ger' => 'https://adminapiger.im.qcloud.com/%s/%s/%s?%s',
        'ind' => 'https://adminapiind.im.qcloud.com/%s/%s/%s?%s',
        'usa' => 'https://adminapiusa.im.qcloud.com/%s/%s/%s?%s',
    ];

    const ENDPOINT_VERSION = 'v4';
    const ENDPOINT_FORMAT = 'json';

    const MAX_USR_NUM = 10;
    const MAX_MSG_NUM = 100;

    private $_client;
    /**
     * 直播管理
     */
    public function __construct($identifier = "administrator")
    {
        $this->sdkappid = env("Tencent.IMAppId");
        $this->_key = env("Tencent.IMKey");
        $this->identifier = $identifier;
        $this->_client = new Client([
            'scheme' => 'tcp',
            'host' => env('redis.host'),
            'port' => env('redis.port'),
            "password" => env('redis.password'),
            "username" => env('redis.username'),

        ]);
        //$this->_client->ping("hh");

    }

    public function SetDebug(bool $isDebuger = false)
    {
        $this->_isDebuger = $isDebuger;
    }

    /**
     * Send request to the IM server.
     *
     * @param string $serverName
     * @param string $command
     * @param array  $params
     *
     * @return array
     */
    public function send(string $serverName, string $command, array $params = []): array
    {
        $endpoint = $this->buildUrl($serverName, $command);
        // $result = $this->postJson($endpoint, $params);

        // return $result;
        return [];
    }

    /**
     * Build the endpoint URL.
     *
     * @param string $serverName
     * @param string $command
     *     *
     * @return string
     */
    protected function buildUrl(string $serverName, string $command): string
    {
        $region = 'zh';
        $endpointTemplate = self::ENDPOINT_TEMPLATES[$region];

        $p = [
            'sdkappid' => env("Tencent.IMAppId"),
            'identifier' => $this->identifier,
            'usersig' => $this->generateSign($this->identifier),
            'random' => random_int(0, 4294967295),
            'contenttype' => self::ENDPOINT_FORMAT,
        ];
        $query = http_build_query($p);

        return sprintf(
            $endpointTemplate,
            self::ENDPOINT_VERSION,
            $serverName,
            $command,
            $query
        );
    }

    /**
     * Generate the user signature.
     *
     * @param string $identifier
     * @param int    $expires
     *
     * @return string
     */
    public function generateSign(string $identifier, int $expires = 15552000): string
    {
        $api = new TLSSigAPIv2($this->sdkappid, $this->_key);
        return $api->genUserSig($identifier, $expires);
    }

    private function json_post($url, $data = null)
    {

        $this->_isDebuger && print_r("-----------------------json_post--------------------" . PHP_EOL);
        $this->_isDebuger && print_r("URL::" . $url . PHP_EOL);
        $curl = curl_init();

        curl_setopt($curl, CURLOPT_URL, $url);
        curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
        curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false);
        if (!$data) {
            return 'data is null';
        }
        if (is_array($data)) {
            $data = json_encode($data);
        }
        $this->_isDebuger && print_r("BODY::" . PHP_EOL);
        $this->_isDebuger && print_r($data);
        $this->_isDebuger && print_r(PHP_EOL . "---------------------" . PHP_EOL);

        curl_setopt($curl, CURLOPT_POST, 1);
        curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
        curl_setopt($curl, CURLOPT_HEADER, 0);
        curl_setopt($curl, CURLOPT_HTTPHEADER, array(
            'Content-Type: application/json; charset=utf-8',
            'Content-Length:' . strlen($data),
            'Cache-Control: no-cache',
            'Pragma: no-cache',
        ));
        curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
        $res = curl_exec($curl);
        $errorno = curl_errno($curl);
        if ($errorno) {
            throw new \Exception("Error Processing Request" . $errorno, 1);
        }
        curl_close($curl);

        $this->_isDebuger && print_r("RESPONSE::" . $res . PHP_EOL);

        $result = json_decode($res, true);
        return $result;
    }

    public function list_all_live_group()
    {
        $url = $this->buildUrl('group_open_http_svc', 'get_appid_group_list');
        $ret = $this->json_post($url, [
            "Limit" => 1000,
        ]);

        print_r($ret);
    }

    public function create_live_group($owner, $type = "AVChatRoom", $name = "")
    {
        $url = $this->buildUrl('group_open_http_svc', 'create_group');
        $ret = $this->json_post($url, [
            "Owner_Account" => $owner, // 群主的 UserId（选填）
            "Type" => $type, // 群组类型：Private/Public/ChatRoom/AVChatRoom/Community
            "Name" => $name, // 群名称（必填）
        ]);

        if (!$ret['ErrorCode']) {
            $group_id = $ret['GroupId'];
            return $group_id;
        } else {
            throw new \Exception("创建群组失败:" . $ret['ErrorCode'] . $ret["ErrorInfo"]);
        }

    }

    public function delete_live_group($groupId)
    {
        $url = $this->buildUrl('group_open_http_svc', 'destroy_group');
        $ret = $this->json_post($url, [
            "GroupId" => $groupId, // 群主的 UserId（选填）
        ]);
        if ($ret['ActionStatus'] == "OK") {
            return true;
        } else {
            //throw new \Exception("删除群组失败:" . $ret['ErrorCode'] . $ret["ErrorInfo"]);
            return false;
        }
    }

    public function message_normal_send_to_group($group_id, $msg, $identifier = "", $operaId = 0, $MsgPriority = "")
    {
        $milliseconds = round(microtime(true) * 1000);

        $url = $this->buildUrl('group_open_http_svc', 'send_group_msg');
        $customData = [
            "no" => md5('administrator' . $milliseconds . $msg),
            "type" => 3,
            "msg" => '',
            'group_id' => $group_id,
        ];
        $message = [
            "GroupId" => $group_id,
            "Random" => random_int(0, 4294967295), // 随机数字，五分钟数字相同认为是重复消息
            "MsgBody" => [ // 消息体，由一个 element 数组组成，详见字段说明
                [
                    "MsgType" => "TIMTextElem", // 文本
                    "MsgContent" => [
                        "Text" => $msg,
                    ],
                ],
            ],
            "CloudCustomData" => json_encode($customData),
            // "SupportMessageExtension" => 0,
            // "OfflinePushInfo" => [
            //     "PushFlag" => 0, // 正常推送，
            //     "Desc" => "离线推送内容",
            //     "Ext" => "这是透传的内容",
            //     "AndroidInfo" => [
            //         "Sound" => "android.mp3",
            //     ],
            //     "ApnsInfo" => [
            //         "Sound" => "apns.mp3",
            //         "BadgeMode" => 1, // 这个字段缺省或者为0表示需要计数，为1表示本条消息不需要计数，即右上角图标数字不增加
            //         "Title" => "apns title", // apns title
            //         "SubTitle" => "apns subtitle", // apns subtitle
            //         "Image" => "www.image.com", // image url
            //     ],
            // ],

        ];

        // 添加 identifier 字段
        if (!empty($identifier)) {
            $message["From_Account"] = $identifier;
        }
        if (!empty($MsgPriority)) {
            $message["MsgPriority"] = $MsgPriority;
        }
        $ret = $this->json_post($url, $message);

        if (!$ret['ErrorCode']) {
            return true;
        } else {
            return $ret["ErrorInfo"];
        }

    }

    //私聊
    public function message_admin_to_user($liveId, $param)
    {
        $url = $this->buildUrl('openim', 'sendmsg'); // 私聊
        $message = [
            "SyncOtherMachine" => 2,
            "From_Account" => $param['send_user'],
            "To_Account" => $param['to_user'],
            "OnlineOnlyFlag" => 1,
            "MsgRandom" => random_int(0, 4294967295), // 随机数字，五分钟数字相同认为是重复消息
            "ForbidCallbackControl" => [
                "ForbidBeforeSendMsgCallback", // 禁止发消息前回调
                //"ForbidAfterSendMsgCallback"  // 禁止发消息后回调
            ],
            "SendMsgControl" => [
                "NoUnread", // 该条消息不计入未读数
                "NoLastMsg", // 该条消息不更新会话列表
                "NoMsgCheck", // 开启云端审核后，该条消息不送审
            ],
            "MsgBody" => [ // 消息体，由一个 element 数组组成，详见字段说明
                [
                    "MsgType" => "TIMTextElem", // 文本
                    "MsgContent" => [
                        "Text" => $param['msg'],
                    ],
                ],
            ],
            "CloudCustomData" => $param['custom_data'],
        ];
        Log::channel("imInfo")->info("message_admin_to_user[]:message:" . json_encode($message));
        $ret = $this->json_post($url, $message);
        Log::channel("imInfo")->info("message_admin_to_user[]:json_post:" . json_encode($ret));
        if (!$ret['ErrorCode']) {
            $this->message_temporary_send_to_administrator($param['msg'], $param['send_user'], $param['custom_data']);
            $params = [];
            $params["MsgTime"] = 0;
            $params["MsgSeq"] = 0;
            $params["CloudCustomData"] = $param['custom_data'];
            $params["MsgBody"] = [['MsgType' => 'TIMTextElem', 'MsgContent' => ['Text' => $param['msg']]]];
            $luss = new LiveUserStaticsService($liveId);
            $luss->OnLiveUserSendMsg($param['send_user'], $params);
            return true;
        } else {
            Log::channel("imInfo")->error("message_admin_to_user[]:err:" . json_encode($ret));
            return $ret["ErrorInfo"];
        }
    }

    //禁言消息发送给administrator暂时更新中控列表
    public function message_temporary_send_to_administrator($msg, $from_account, $cloud)
    {
        $num = mt_rand(0, 1);
        if ($num == 0) {
            $gid = 3;
        } else {
            $gid = 2;
        }
        $userData = DB::name('siyu_sys_member')->where('is_control', 1)
            ->where('group_id', '<>', $gid)->select();
        $userList = ['administrator'];
        foreach ($userData as $item) {
            if ($item['uid'] == 1) {
                $userList[] = 'administrator';
            } else {
                if ('M_' . env("Live.live_pre") . $item['uid'] != $from_account) {
                    $userList[] = 'M_' . env("Live.live_pre") . $item['uid'];
                }
                if ('C_' . env("Live.live_pre") . $item['uid'] != $from_account) {
                    $userList[] = 'C_' . env("Live.live_pre") . $item['uid'];
                }
            }
        }
        //添加账号前缀
        $from_account = User::addPreToAccout($from_account);
        //$url = $this->buildUrl('openim', 'sendmsg');  // 私聊
        $url = $this->buildUrl('openim', 'batchsendmsg'); // 批量私聊
        $message = [
            "SyncOtherMachine" => 2,
            "From_Account" => $from_account,
            "To_Account" => $userList,
            "OnlineOnlyFlag" => 1,
            "MsgRandom" => random_int(0, 4294967295), // 随机数字，五分钟数字相同认为是重复消息
            "ForbidCallbackControl" => [
                "ForbidBeforeSendMsgCallback", // 禁止发消息前回调
                //"ForbidAfterSendMsgCallback", // 禁止发消息后回调
            ],
            "SendMsgControl" => [
                "NoUnread", // 该条消息不计入未读数
                "NoLastMsg", // 该条消息不更新会话列表
                "NoMsgCheck", // 开启云端审核后，该条消息不送审
            ],
            "MsgBody" => [ // 消息体，由一个 element 数组组成，详见字段说明
                [
                    "MsgType" => "TIMTextElem", // 文本
                    "MsgContent" => [
                        "Text" => $msg,
                    ],
                ],
            ],
            "CloudCustomData" => $cloud,
        ];
        //Log::channel("imInfo")->info("message_temporary_send_to_[]:send:" . json_encode($message));
        $ret = $this->json_post($url, $message);
        //Log::channel("imInfo")->info("message_temporary_send_to_[]:json_post:" . json_encode($ret));
        if (!$ret['ErrorCode']) {
            return true;
        } else {
            Log::channel("imInfo")->error("message_temporary_send_to_[]:err:" . json_encode($ret));
            return $ret["ErrorInfo"];
        }

    }

    public function message_system_notify_send_to_group($group_id, $msg)
    {
        $url = $this->buildUrl('group_open_http_svc', 'send_group_system_notification');
        $message = [
            "GroupId" => $group_id,
            "Content" => $msg, // 系统通知内容
        ];

        $ret = $this->json_post($url, $message);

        if (!$ret['ErrorCode']) {

            return true;
        } else {
            Log::channel("imInfo")->info("ImCallback:command:error" . json_encode($ret));
            return $ret["ErrorInfo"];
        }

    }

    public function message_broadcase_send_to_group($msg)
    {
        $url = $this->buildUrl('group_open_http_svc', 'send_broadcast_msg');
        $message = [
            "Random" => random_int(0, 4294967295), // 随机数字，五分钟数字相同认为是重复消息
            "MsgBody" => [ // 消息体，由一个 element 数组组成，详见字段说明
                [
                    "MsgType" => "TIMTextElem", // 文本
                    "MsgContent" => [
                        "Text" => $msg,
                    ],
                ],
            ],

        ];

        $ret = $this->json_post($url, $message);

        print_r($ret);

    }

    //用户禁言
    public function user_mute($userId, $liveId = 0, $time = 10800, $is_trust = false)
    {
        if (!$is_trust) {
            return;
        }
        $Key = env("redis.prefix") . 'live:user:mute:liveId_' . $liveId;
        if (!$this->_client->exists($Key)) {
            // 禁言缓存不存在，添加
            $this->_client->hset($Key, $userId, $time);
        } else {
            if (!$this->_client->hexists($Key, $userId)) {
                // 用户不存在，添加
                $this->_client->hset($Key, $userId, $time);
            }
            //else {
            //    // 用户已禁言
            //    return true;
            //}
        }

        $url = $this->buildUrl('openconfigsvr', 'setnospeaking');
        $message = [
            "Set_Account" => $userId,
            "GroupmsgNospeakingTime" => $time,
        ];
        $ret = $this->json_post($url, $message);
        DB::table('xh_siyu_user_remark')->save(['remark' => '获取状态时-禁言用户：' . json_encode([$ret, $userId, $liveId, $time, $is_trust])]);
        if (!$ret['ErrorCode']) {
            return true;
        } else {
            return $ret["ErrorInfo"];
        }
    }

    public function account_import_one($userId, $nickName, $faceUrl)
    {
        $url = $this->buildUrl('im_open_login_svc', 'account_import');
        $message = [
            "UserID" => $userId,
            "Nick" => $nickName,
            "FaceUrl" => $faceUrl,
        ];
        $ret = $this->json_post($url, $message);
        if (!$ret['ErrorCode']) {

            return true;
        } else {
            return $ret["ErrorInfo"];
        }
    }
    public function account_import_many(array $ids)
    {
        $url = $this->buildUrl('im_open_login_svc', 'account_import');
        $message = [
            "AccountList" => $ids,
        ];
        $ret = $this->json_post($url, $message);
        if (!$ret['ErrorCode']) {
            return $ret;
        } else {
            return $ret["ErrorInfo"];
        }
    }

    public function account_query_one($ids)
    {

        $url = $this->buildUrl('im_open_login_svc', 'account_check');
        $message = [
            "CheckItem" => [],
        ];
        foreach ($ids as $id) {
            $message["CheckItem"][] = [
                "UserID" => $id,
            ];
        }
        $ret = $this->json_post($url, $message);
        if (!$ret['ErrorCode']) {
            return $ret["ResultItem"];
        } else {
            return $ret["ErrorInfo"];
        }
    }

    /**
     * 批量删除账号
     *
     * @param array $ids
     * @return bool|string
     */
    public function account_delete_ids(array $ids)
    {
        $url = $this->buildUrl('im_open_login_svc', 'account_delete');
        $message = [
            "DeleteItem" => [],
        ];
        foreach ($ids as $id) {
            $message["DeleteItem"][] = [
                "UserID" => $id,
            ];
        }
        $ret = $this->json_post($url, $message);
        if (!$ret['ErrorCode']) {

            return true;
        } else {
            return $ret["ErrorInfo"];
        }
    }

    public function get_live_group_user_count($group_id)
    {
        $url = $this->buildUrl('group_open_http_svc', 'get_online_member_num');
        $message = [
            "GroupId" => $group_id,
        ];
        $ret = $this->json_post($url, $message);
        if (!$ret['ErrorCode']) {
            return $ret['OnlineMemberNum'];
        }
        throw new Exception("获取直播间人数错误!" . $ret["ErrorInfo"]);
    }

    public function forbid_some_user_with_times($groupId, $ids, $times)
    {
        $url = $this->buildUrl('group_open_http_svc', 'forbid_send_msg');
        $message = [
            "GroupId" => $groupId,
            "Members_Account" => $ids,
            "MuteTime" => $times,
        ];

        $ret = $this->json_post($url, $message);
        if (!$ret['ErrorCode']) {
            return true;
        } else {
            return false;
        }
    }

    public function get_group_forbid_users_list($groupId)
    {
        $url = $this->buildUrl('group_open_http_svc', 'get_group_muted_account');
        $message = [
            "GroupId" => $groupId,
        ];

        $ret = $this->json_post($url, $message);
        if (!$ret['ErrorCode']) {
            return $ret['MutedAccountList'];
        } else {
            return false;
        }
    }

    public function ban_some_user_form_group($groupId, $ids, $msg, $duration = 3600)
    {
        $url = $this->buildUrl('group_open_http_svc', 'ban_group_member');
        $message = [
            "GroupId" => $groupId,
            "Members_Account" => $ids,
            "Duration" => $duration, //封禁时长，单位是秒
            "Description" => $msg, //封禁信息，最大长度1000字节
        ];

        $ret = $this->json_post($url, $message);
        if (!$ret['ErrorCode']) {
            return true;
        } else {
            return false;
        }
    }

    public function unban_some_user_form_group($groupId, $ids)
    {
        $url = $this->buildUrl('group_open_http_svc', 'unban_group_member');
        $message = [
            "GroupId" => $groupId,
            "Members_Account" => $ids,
        ];

        $ret = $this->json_post($url, $message);
        if (!$ret['ErrorCode']) {
            return true;
        } else {
            return false;
        }
    }

    public function redis_add_online_user($groupId, $UserIds)
    {
        Log::channel("imInfo")->info("redis_add_online_user:add:" . json_encode($UserIds));
        $livestatus = new LiveStatus(null);
        $liveId = $livestatus->GetLiveIdByGroupId($groupId);
        // 直播间在线用户列表
        $Key = env("redis.prefix") . "live:list:" . $liveId . ":online_user:list";
        $MapKey = env("redis.prefix") . "live:list:" . $liveId . ":online_user:map";

        //去前缀，否则报错  其他家使用时
        $UserIds2 = [];
        foreach ($UserIds as $v) {
            $UserIds2[] = explode(env("Live.live_pre"), $v)[1];
        }

        $offline_user_infos = [];
        $userInfo = Db::name("siyu_user")->where("id", "in", $UserIds2)->select()->toArray();
        if (!empty($userInfo)) {
            array_walk($userInfo, function ($value, $key) use (&$offline_user_infos) {
                $offline_user_infos[] = json_encode([
                    "user_id" => $value["id"],
                    "user_name" => $value["nickname"],
                    "user_avatar" => $value["wx_avatarurl"],
                ]);
            });
        }

        $this->_client->pipeline(function ($pipe) use ($Key, $offline_user_infos, $MapKey) {
            foreach ($offline_user_infos as $k => $item) {
                $pipe->lrem($Key, 0, $item);
                $pipe->lpush($Key, $item);
                $pipe->hset($MapKey, $item, "1");
            }
        });
    }

    public function redis_remove_onlin_user($groupId, $UserIds)
    {

        $livestatus = new LiveStatus(null);
        $liveId = $livestatus->GetLiveIdByGroupId($groupId);

        Log::channel("imInfo")->info("redis_add_online_user:remove:" . $groupId . json_encode($UserIds));

        $Key = env("redis.prefix") . "live:list:" . $liveId . ":online_user:list";
        $MapKey = env("redis.prefix") . "live:list:" . $liveId . ":online_user:map";

        //去前缀，否则报错  其他家使用时
        $UserIds2 = [];
        foreach ($UserIds as $v) {
            $UserIds2[] = explode(env("Live.live_pre"), $v)[1];
        }

        $offline_user_infos = [];
        $userInfo = Db::name("siyu_user")->where("id", "in", $UserIds2)->select()->toArray();
        if (!empty($userInfo)) {
            array_walk($userInfo, function ($value, $key) use (&$offline_user_infos) {
                $offline_user_infos[] = json_encode([
                    "user_id" => $value["id"],
                    "user_name" => $value["nickname"],
                    "user_avatar" => $value["wx_avatarurl"],
                ]);
            });
        }

        $this->_client->pipeline(function ($pipe) use ($Key, $offline_user_infos, $MapKey) {
            foreach ($offline_user_infos as $k => $value) {
                $pipe->lrem($Key, 0, $value);
                $pipe->hset($MapKey, $value, "0");
            }
        });
    }

    public function redis_get_online_user($groupId)
    {
        $livestatus = new LiveStatus(null);
        $liveId = $livestatus->GetLiveIdByGroupId($groupId);
        $Key = env("redis.prefix") . "live:list:" . $liveId . ":online_user:list";
        return $this->_client->lrange($Key, 0, self::MAX_USR_NUM);
    }

    public function redis_get_online_user_num($groupId)
    {
        $livestatus = new LiveStatus(null);
        $liveId = $livestatus->GetLiveIdByGroupId($groupId);

        $Key = env("redis.prefix") . "live:list:" . $liveId . ":online_user:list";
        return $this->_client->llen($Key);
    }

    /***************************************** 违禁消息暂存列表 ************************************************/
    // 添加违禁消息
    public function redis_add_illegal_msg($groupId, $msg)
    {
        $livestatus = new LiveStatus(null);
        $liveId = $livestatus->GetLiveIdByGroupId($groupId);
        // 直播间禁言消息列表
        $Key = env("redis.prefix") . "live:list:" . $liveId . ":illegal_msg";
        $Info = LiveUserStaticsService::getUserInfo($msg["From_Account"]);
        if (empty($Info)) {
            return false;
        }
        $item = [
            "id" => $Info["id"],
            "mid" => $msg["id"],
            "msg" => $msg["MsgBody"],
            "nickname" => $Info["nickname"],
            "avatar" => $Info['wx_avatarurl'],
            "im_id" => $msg["From_Account"],
            "cloud_custom_data" => $msg["CloudCustomData"],
            "no" => $msg["no"],
            "random_id" => $msg["random_id"],
            "is_illegal" => $msg["is_illegal"],
            "is_silence" => $msg["is_silence"],
            "is_hide" => $msg["is_hide"],
        ];
        $ret = json_encode($item);

        // 用哈希列表来存msg
        return $this->_client->hset($Key, $msg['no'], $ret);
    }
    // 读取违禁消息列表
    public function redis_get_illegal_msg($groupId)
    {
        $livestatus = new LiveStatus(null);
        $liveId = $livestatus->GetLiveIdByGroupId($groupId);
        $Key = env("redis.prefix") . "live:list:" . $liveId . ":illegal_msg";
        if (!$this->_client->exists($Key)) {
            return [];
        }

        $list = $this->_client->hvals($Key);
        $list = array_map(function ($item) {
            return json_decode($item, true);
        }, $list);
        return $this->sortByField($list, 'mid');
    }

    /***************************************** 隐藏消息暂存列表 ************************************************/
    // 更新某条隐藏信息
    public function redis_set_hide_msg($groupId, $field, $newMsg)
    {
        $livestatus = new LiveStatus(null);
        $liveId = $livestatus->GetLiveIdByGroupId($groupId);

        // 违禁列表添加隐藏状态
        $msgIllegalKey = env("redis.prefix") . "live:list:" . $liveId . ":illegal_msg";
        if ($this->_client->exists($msgIllegalKey)) {
            $msgList = $this->_client->hvals($msgIllegalKey);
            array_map(function ($item) use ($newMsg, $msgIllegalKey) {
                $json = json_decode($item, true);
                if ($json['id'] == $newMsg['id']) {
                    $json["is_hide"] = $newMsg['is_hide'];
                    $data = json_encode($json);
                    $this->_client->hset($msgIllegalKey, $json["no"], $data);
                }
                return $json;
            }, $msgList);
        }

        // 禁言列表添加隐藏状态
        $msgSilenceKey = env("redis.prefix") . "live:list:" . $liveId . ":silence_msg";
        if ($this->_client->exists($msgSilenceKey)) {
            $msgList = $this->_client->hvals($msgSilenceKey);
            array_map(function ($item) use ($newMsg, $msgSilenceKey) {
                $json = json_decode($item, true);
                if ($json['id'] == $newMsg['id']) {
                    $json["is_hide"] = $newMsg['is_hide'];
                    $data = json_encode($json);
                    $this->_client->hset($msgSilenceKey, $json["no"], $data);
                }
                return $json;
            }, $msgList);
        }

        // 隐藏列表添加隐藏消息
        $Key = env("redis.prefix") . "live:list:" . $liveId . ":hide_msg";
        if ($newMsg['is_hide']) {
            $newMsg = json_encode($newMsg);
            return $this->_client->hset($Key, $field, $newMsg);
        }
        return $this->_client->hdel($Key, $field);
    }
    // 读取隐藏消息列表
    public function redis_get_hide_msg($groupId)
    {
        $livestatus = new LiveStatus(null);
        $liveId = $livestatus->GetLiveIdByGroupId($groupId);
        $Key = env("redis.prefix") . "live:list:" . $liveId . ":hide_msg";
        if (!$this->_client->exists($Key)) {
            return [];
        }

        $list = $this->_client->hvals($Key);
        $list = array_map(function ($item) {
            return json_decode($item, true);
        }, $list);
        return $list;
        //return $this->sortByField($list, 'mid');
    }

    /***************************************** 禁言消息暂存列表 ************************************************/
    // 添加禁言消息
    public function redis_add_silence_msg($groupId, $msg)
    {
        $livestatus = new LiveStatus(null);
        $liveId = $livestatus->GetLiveIdByGroupId($groupId);
        // 禁言列表添加禁言
        $Key = env("redis.prefix") . "live:list:" . $liveId . ":silence_msg";
        $Info = LiveUserStaticsService::getUserInfo($msg["From_Account"]);

        if (empty($Info)) {
            $Info['id'] = $msg["From_Account"];
            $Info['nickname'] = '助教老师';
            $Info['avatar'] = 'https://chongchongdushu-1251993779.cos.ap-shanghai.myqcloud.com/image/20240530/png/6657ff2f9e9e6.png';
        }

        $item = [
            "id" => $Info["id"],
            "mid" => $msg["id"],
            "msg" => $msg["MsgBody"],
            "nickname" => $Info["nickname"],
            "avatar" => $Info['wx_avatarurl'],
            "im_id" => $msg["From_Account"],
            "cloud_custom_data" => $msg["CloudCustomData"],
            "no" => $msg["no"],
            "type" => $msg['type'],
            "random_id" => $msg["random_id"],
            "is_illegal" => $msg["is_illegal"],
            "is_silence" => $msg["is_silence"],
            "is_hide" => $msg["is_hide"],
            "is_digit_man" => $msg["is_digit_man"],
        ];
        $ret = json_encode($item);
        $this->_client->hset($Key, $msg["no"], $ret);
    }
    // 设置禁言消息
    public function redis_set_silence_msg($groupId, $msg)
    {
        $livestatus = new LiveStatus(null);
        $liveId = $livestatus->GetLiveIdByGroupId($groupId);
        // 禁言列表添加禁言
        $Key = env("redis.prefix") . "live:list:" . $liveId . ":silence_msg";
        $msgKey = env("redis.prefix") . "live:list:" . $liveId . ":msg";
        if ($this->_client->exists($msgKey)) {
            $msgList = $this->_client->hvals($msgKey);
            array_map(function ($item) use ($msg, $Key) {
                $json = json_decode($item, true);
                if ($json['id'] == $msg['id']) {
                    $json["is_silence"] = 1;
                    $data = json_encode($json);
                    $this->_client->hset($Key, $json["no"], $data);
                }
                return $json;
            }, $msgList);
        }
        // 隐藏列表添加禁言状态
        $msgHideKey = env("redis.prefix") . "live:list:" . $liveId . ":hide_msg";
        if ($this->_client->exists($msgHideKey)) {
            $msgList = $this->_client->hvals($msgHideKey);
            array_map(function ($item) use ($msg, $msgHideKey) {
                $json = json_decode($item, true);
                if ($json['id'] == $msg['id']) {
                    $json["is_silence"] = 1;
                    $data = json_encode($json);
                    $this->_client->hset($msgHideKey, $json["no"], $data);
                }
                return $json;
            }, $msgList);
        }
        // 违禁列表添加禁言状态
        $msgIllegalKey = env("redis.prefix") . "live:list:" . $liveId . ":illegal_msg";
        if ($this->_client->exists($msgIllegalKey)) {
            $msgList = $this->_client->hvals($msgIllegalKey);
            array_map(function ($item) use ($msg, $msgIllegalKey) {
                $json = json_decode($item, true);
                if ($json['id'] == $msg['id']) {
                    $json["is_silence"] = 1;
                    $data = json_encode($json);
                    $this->_client->hset($msgIllegalKey, $json["no"], $data);
                }
                return $json;
            }, $msgList);
        }
        return true;
    }
    // 解除某个用户禁言
    public function redis_relieve_silence_msg($groupId, $field)
    {
        $livestatus = new LiveStatus(null);
        $liveId = $livestatus->GetLiveIdByGroupId($groupId);
        $Key = env("redis.prefix") . "live:list:" . $liveId . ":silence_msg";
        return $this->del_silence_list($Key, $field);
    }
    // 读取禁言消息列表
    public function redis_get_silence_msg($groupId)
    {
        $livestatus = new LiveStatus(null);
        $liveId = $livestatus->GetLiveIdByGroupId($groupId);
        $Key = env("redis.prefix") . "live:list:" . $liveId . ":silence_msg";
        if (!$this->_client->exists($Key)) {
            return [];
        }

        $list = $this->_client->hvals($Key);
        $list = array_map(function ($item) {
            return json_decode($item, true);
        }, $list);
        $list = $this->sortByField($list, 'mid');
        if (count($list) > self::MAX_MSG_NUM) {
            $list = array_slice($list, -self::MAX_MSG_NUM);
            $del_list = array_slice($list, 0, count($list) - self::MAX_MSG_NUM);
        }
        if (!empty($del_list)) {
            foreach ($del_list as $item) {
                $this->_client->hdel($Key, $item['no']);
            }
        }
        return $list;
    }

    /***************************************** 消息暂存列表 上限3000条 ************************************************/
    // 添加在线消息
    public function redis_add_online_msg($groupId, $msg, $type = 0)
    {

        Log::channel("imInfo")->info("redis_add_online_msg:" . $groupId . json_encode($msg));
        $livestatus = new LiveStatus(null);
        $liveId = $livestatus->GetLiveIdByGroupId($groupId);
        // 直播间在线用户列表
        $Key = env("redis.prefix") . "live:list:" . $liveId . ":msg";
        $KeyAll = env("redis.prefix") . "live:list:" . $liveId . ":msg_all";
        // $Info = Db::name("siyu_user")->where("id", $msg["From_Account"])->find();
        $Info = LiveUserStaticsService::getUserInfo($msg["From_Account"]);
        Log::channel("imInfo")->info("redis_add_online_msg:getUserInfo:" . json_encode($Info));

        if (empty($Info)) {
            //Log::channel("imInfo")->info("redis_add_online_msg:getUserInfo:cancale:null userInfo!!!");
            //return;
            $Info['id'] = $msg["From_Account"];
            $Info['nickname'] = '助教老师';
            $Info['avatar'] = 'https://chongchongdushu-1251993779.cos.ap-shanghai.myqcloud.com/image/20240530/png/6657ff2f9e9e6.png';
        }
        //  这里看看需要过滤 admin 的数据
        // if ($Info["type"] == "a") {
        //     Log::channel("imInfo")->info("redis_add_online_msg:getUserInfo:cancale:admin:msg!!!");
        //     return;
        // }

        $item = [
            "mid" => $msg["id"],
            "msg" => $msg["MsgBody"],
            "nickname" => $Info["nickname"],
            "avatar" => $Info['wx_avatarurl'],
            "im_id" => $msg["From_Account"],
            "cloud_custom_data" => $msg["CloudCustomData"],
            "no" => $msg["no"],
            "type" => $msg['type'],
            "random_id" => $msg["random_id"],
            "is_illegal" => $msg["is_illegal"],
            "is_silence" => $msg["is_silence"],
            "is_hide" => $msg["is_hide"],
            "is_digit_man" => $msg["is_digit_man"],
        ];
        $pos = strpos($Info["id"], env("Live.live_pre"));
        if ($pos === false) {
            $item['id'] = env("Live.live_pre") . $Info["id"];
        } else {
            $item['id'] = $Info["id"];
        }

        $ret = json_encode($item);

        if ($type == 6) {
            //禁言
            $KeySilence = env("redis.prefix") . "live:list:" . $liveId . ":silence_msg";
            $this->_client->hset($KeySilence, $msg["no"], $ret);
            $lenSilence = $this->_client->hlen($KeySilence);
            if ($lenSilence > self::MAX_MSG_NUM) {
                $list = $this->_client->hvals($KeySilence);
                $list = array_map(function ($item) {
                    return json_decode($item, true);
                }, $list);
                $list = $this->sortByField($list, 'mid');
                $list = array_slice($list, 0, $lenSilence - self::MAX_MSG_NUM);
                if (!empty($list)) {
                    foreach ($list as $item) {
                        $this->_client->hdel($KeySilence, $item['no']);
                    }
                }
            }
        } elseif ($type == 7) {
            //违禁词
            $KeyIllegal = env("redis.prefix") . "live:list:" . $liveId . ":illegal_msg";
            $this->_client->hset($KeyIllegal, $msg["no"], $ret);
        }

        // 用哈希列表来存msg
        if ($type != 3 && $type != 4) {
            $this->_client->hset($Key, $msg["no"], $ret);
            $len = $this->_client->hlen($Key);
            if ($len > self::MAX_MSG_NUM) {
                //Log::channel("imInfo")->info("redis_add_online_msg:ltrim:[".$len."]len:[".self::MAX_MSG_NUM.']');
                $list = $this->_client->hvals($Key);
                $list = array_map(function ($item) {
                    return json_decode($item, true);
                }, $list);
                $list = $this->sortByField($list, 'mid');
                $list = array_slice($list, 0, $len - self::MAX_MSG_NUM);
                if (!empty($list)) {
                    foreach ($list as $item) {
                        $this->_client->hdel($Key, $item['no']);
                    }
                }
            }
        }
        $this->_client->hset($KeyAll, $msg["no"], $ret);
        $len = $this->_client->hlen($KeyAll);
        if ($len > 500) {
            $listAll = $this->_client->hvals($KeyAll);
            $listAll = array_map(function ($item) {
                return json_decode($item, true);
            }, $listAll);
            $listAll = $this->sortByField($listAll, 'mid');
            $listAll = array_slice($listAll, 0, $len - 500);
            if (!empty($listAll)) {
                foreach ($listAll as $item) {
                    $this->_client->hdel($KeyAll, $item['no']);
                }
            }
        }
        return true;
    }

    public function redis_set_online_msg($groupId, $field, $newMsg)
    {
        $livestatus = new LiveStatus(null);
        $liveId = $livestatus->GetLiveIdByGroupId($groupId);

        $Key = env("redis.prefix") . "live:list:" . $liveId . ":msg";
        $find = $this->_client->hget($Key, $field);
        if (!$find) {
            return false;
        }

        $find = json_decode($find, true);
        if (empty($newMsg['is_illegal'])) {
            $find['is_illegal'] = 0;
        } else {
            $find['is_illegal'] = 1;
        }
        if (empty($newMsg['is_hide'])) {
            $find['is_hide'] = 0;
        } else {
            $find['is_hide'] = 1;
        }
        if (empty($newMsg['is_silence'])) {
            $find['is_silence'] = 0;
        } else {
            $find['is_silence'] = 1;
        }
        $this->set_silence_list($Key, $newMsg['id'], $newMsg['is_silence']);
        $data = json_encode($find);
        return $this->_client->hset($Key, $field, $data);
    }

    public function redis_get_online_msg($groupId, $leng = 0)
    {
        $livestatus = new LiveStatus(null);
        $liveId = $livestatus->GetLiveIdByGroupId($groupId);
        $Key = env("redis.prefix") . "live:list:" . $liveId . ":msg";
        if (!$this->_client->exists($Key)) {
            return [];
        }

        $list = $this->_client->hvals($Key);
        $list = array_map(function ($item) {
            return json_decode($item, true);
        }, $list);
        $list = $this->sortByField($list, 'mid');
        if ($leng > 0) {
            $list = array_slice($list, -$leng);
        }
        return $list;
    }

    public function redis_get_online_msg_all($groupId, $leng = 0)
    {
        $livestatus = new LiveStatus(null);
        $liveId = $livestatus->GetLiveIdByGroupId($groupId);
        $Key = env("redis.prefix") . "live:list:" . $liveId . ":msg_all";
        if (!$this->_client->exists($Key)) {
            return [];
        }

        $list = $this->_client->hvals($Key);
        $list = array_map(function ($item) {
            return json_decode($item, true);
        }, $list);
        $list = $this->sortByField($list, 'mid');
        if ($leng > 0) {
            $list = array_slice($list, -$leng);
        }
        return $list;
    }

    // 二维数组按某字段排序
    public static function sortByField($array, $field, $direction = 'asc')
    {
        usort($array, function ($a, $b) use ($field, $direction) {
            $sortOrder = strtolower($direction) == 'asc' ? 1 : -1;
            return ($a[$field] < $b[$field]) ? -$sortOrder : $sortOrder;
        });
        return $array;
    }

    // 更新消息列表-禁言用户的数据状态
    public function set_silence_list($key, $id, $is_silence)
    {
        if (!$this->_client->exists($key)) {
            return false;
        }

        $list = $this->_client->hvals($key);
        foreach ($list as $item) {
            $item = json_decode($item, true);
            if ($item['id'] == $id) {
                $item['is_silence'] = $is_silence;
                $data = json_encode($item);
                $this->_client->hset($key, $item['no'], $data);
            }
        }
        return true;
    }

    // 删除禁言列表-解除禁言的数据
    public function del_silence_list($key, $id)
    {
        if (!$this->_client->exists($key)) {
            return false;
        }

        $list = $this->_client->hvals($key);
        foreach ($list as $item) {
            $item = json_decode($item, true);
            if ($item['id'] == $id) {
                $this->_client->hdel($key, $item['no']);
            }
        }
        return true;
    }

}
